import { Logger } from "@nestjs/common";
import { CorsOptions, CorsOptionsDelegate } from "@nestjs/common/interfaces/external/cors-options.interface";
import { registerAs } from "@nestjs/config";
import session from "express-session";
import { resolve } from "path";

import * as PACKAGE_JSON from "../../../package.json";
import { IS_PROD_ENV } from "../constant/global-enum";
import { HttpUtils } from "../utils/HttpUtils";
import { API_DEFAULT_GLOBAL_VERSION, API_PREFIX, SERVER_PORT, SWAGGER_PATH, UPLOAD_FOLDER } from "./config-data";

export enum CONFIG_KEY {
    project = "project",
    server = "server",
    logger = "logger",
    cors = "cors",
    swagger = "swagger",
    upload = "upload",
    session = "session",
    captcha = "captcha"
}

const ProjectConfig = registerAs(CONFIG_KEY.project, () => ({
    name: PACKAGE_JSON.name,
    version: PACKAGE_JSON.version,
    description: PACKAGE_JSON.description,
    author: PACKAGE_JSON.author
}));

const ServerConfig = registerAs(CONFIG_KEY.server, () => ({
    apiPrefix: API_PREFIX,
    apiDefaultGlobalVersion: API_DEFAULT_GLOBAL_VERSION,
    appStage: process.env.NODE_ENV,
    port: IS_PROD_ENV ? SERVER_PORT.prod : SERVER_PORT.dev,
    appServerUrlPrefix: `${API_PREFIX}/v${API_DEFAULT_GLOBAL_VERSION}`
}));

const LoggerConfig = registerAs(CONFIG_KEY.logger, () => ({
    level: process.env.LOG_LEVEL || (process.env.NODE_ENV === "production" ? "info" : "debug"),
    logDir: process.env.LOG_DIR || "logs",
    maxFiles: process.env.LOG_MAX_FILES || "14d",
    maxSize: process.env.LOG_MAX_SIZE || "20m"
}));

export interface CorsConfigType {
    enabled: boolean;
    corsOptons: CorsOptions | CorsOptionsDelegate<any>;
}
const CorsConfig = registerAs(
    CONFIG_KEY.cors,
    (): CorsConfigType => ({
        enabled: true,
        corsOptons: {
            origin: IS_PROD_ENV
                ? [`http://localhost:${SERVER_PORT.prod}`] // "生产环境允许的源"
                : (origin, callback) => {
                      //   console.log("request origin:", origin);
                      Logger.debug(`request origin: ${origin}`, "CorsConfig");
                      // 开发环境对所有本地或局域网源允许跨域，对网页版apifox也允许跨域
                      if (
                          !origin ||
                          HttpUtils.isLocalOrLanOrigin(origin) ||
                          origin === "https://app.apifox.com" ||
                          origin === "chrome-extension://eggdlmopfankeonchoflhfoglaakobma"
                      ) {
                          // 如果是本地或局域网源，则允许跨域
                          callback(null, true);
                      } else {
                          callback(new Error("Not allowed by CORS"));
                      }
                  }, // 允许跨域的源，设置为 "*" 表示允许所有源
            allowedHeaders:
                "Content-Type,Authorization,Set-Cookie,Access-Control-Allow-Origin,Cache-Control,Pragma,Version",
            methods: "GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS",
            exposedHeaders: "x-custom-header", // 跨域时，允许暴露的响应头
            credentials: true // 跨域时，是否前端允许携带cookie，注意：如果设置为true，则 origin 不能为 *，必须明确指定允许的源
        }
    })
);

const SwaggerConfig = registerAs(CONFIG_KEY.swagger, () => ({
    enabled: IS_PROD_ENV ? false : true,
    path: SWAGGER_PATH.docPath,
    jsonPath: SWAGGER_PATH.jsonPath,
    yamlPath: SWAGGER_PATH.yamlPath
}));

const UploadConfig = registerAs(CONFIG_KEY.upload, () => ({
    dest: resolve(process.cwd(), UPLOAD_FOLDER), // 项目根目录，所有文件平铺到 uploads 文件夹下
    limits: {
        fileSize: 1024 * 1024 * 1024, // 最大文件大小 1G
        files: 100, // 最大文件数量 100
        fields: 100, // 最大非文件字段数量 100
        parts: 100 // 最大字段数量（文件+非文件） 100
    }
}));

export interface SessionConfigType {
    enabled: boolean;
    sessionOptions: session.SessionOptions;
}

const SessionConfig = registerAs(
    CONFIG_KEY.session,
    (): SessionConfigType => ({
        enabled: false,
        sessionOptions: {
            secret: "protect the best kunkun",
            resave: false,
            saveUninitialized: false,
            cookie: {
                maxAge: 1000 * 60 * 60 * 24 * 7, // 7 days
                httpOnly: true,
                secure: false,
                sameSite: "strict"
            }
        }
    })
);

const CaptchaConfig = registerAs(CONFIG_KEY.captcha, () => ({
    enabled: false,
    expired: 60 * 1000
}));

export const configModules = [
    ProjectConfig,
    ServerConfig,
    LoggerConfig,
    CorsConfig,
    SwaggerConfig,
    UploadConfig,
    SessionConfig,
    CaptchaConfig
];

// registerAs("config", () => ({
//     project: {
//         apiPrefix: process.env.API_PREFIX || "api",
//         name: PACKAGE_JSON.name,
//         version: PACKAGE_JSON.version,
//         description: PACKAGE_JSON.description,
//         author: PACKAGE_JSON.author
//     },
//     server: {
//         isProd: process.env.NODE_ENV === "production",
//         appStage: process.env.APP_STAGE,
//         port: parseInt(process.env.PORT, 10) || 8080,
//         context: process.env.CONTEXT || "v1",
//         origins: process.env.ORIGINS ? process.env.ORIGINS.split(",") : "*",
//         allowedHeaders: process.env.ALLOWED_HEADERS,
//         allowedMethods: process.env.ALLOWED_METHODS,
//         propagateHeaders: process.env.PROPAGATE_HEADERS ? process.env.PROPAGATE_HEADERS.split(",") : [],
//         corsEnabled: process.env.CORS_ENABLED.toLowerCase() === "true",
//         corsCredentials: process.env.CORS_CREDENTIALS.toLowerCase() === "true"
//     },
//     swagger: {
//         path: process.env.SWAGGER_PATH || "docs",
//         enabled: process.env.SWAGGER_ENABLED.toLowerCase() === "true"
//     },
//     tracing: {
//         resourceAttributes: {
//             serviceName: `${PACKAGE_JSON.name}`,
//             version: PACKAGE_JSON.version,
//             "service.namespace": `${process.env.API_PREFIX}`,
//             "deployment.environment": process.env.APP_STAGE
//         },
//         exporter: {
//             url: process.env.TRACING_ENDPOINT,
//             headers: {
//                 Authorization: `${process.env.TRACING_AUTH_TOKEN}`
//             }
//         }
//     },
//     params: {
//         testEnv: process.env.TEST_KEY
//     },
//     services: {
//         rickAndMortyAPI: {
//             url: process.env.RICK_AND_MORTY_API_URL,
//             timeout: 3000,
//             healthPath: process.env.RICK_AND_MORTY_API_URL_LIVENESS
//         }
//     }
// }));
